/**
 * laya fairygui 封装
 */
const PageMap: Map<string, any> = new Map();
// 页面特效，加载完页面即播放
const EFFECT_LOAD_NAME = 'effect_load'

// 加载 package
export const loadPackage = (packageName, callBack) => {
    let handle = callBack instanceof Laya.Handler ? callBack : Laya.Handler.create(null, callBack);
    fgui.UIPackage.loadPackage(`res/UI/${packageName}`, handle);
};

export const createObject = fgui.UIPackage.createObject

interface BindArgs {
    view: string,
    route?: string
}
// 与视图绑定
export const view = (args: string | BindArgs) => {
    let path, route;
    if (typeof args == "string") {
        path = args;
    } else {
        ({ view: path, route } = args);
    }
    return function (target) {
        let { packageName, page } = View.resolve(path);
        let parent = Object.getPrototypeOf(target);
        let proto = target.prototype;
        route && PageMap.set(route, target);
        // 界面和弹窗处理
        if (parent == View) {
            proto.load = function () {
                this.page = page;
                this.packageName = packageName;
                loadPackage(packageName, Laya.Handler.create(this, this.onUILoaded));
            }
        } else {
            proto.load = function () {
                let _this = this;
                this.page = page;
                this.packageName = packageName;
                let loadOpts = { fileName: `${path}.ui`, loaded: false, load: loadFunc };
                function loadFunc(callBack, ctx) {
                    loadPackage(packageName, () => {
                        loadOpts.loaded = true;
                        callBack.call(ctx);
                        _this.attach()
                    });
                }
                this.addUISource(loadOpts);
            }
        }
    }
}
// 获取组件
export const component = (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => {
    let privateKey = '_' + propertyKey;
    if (!descriptor) {
        Object.defineProperty(target, propertyKey, {
            configurable: true,
            set: function (value: any) {
                this[privateKey] = value;
            },
            get: function () {
                if (!this[privateKey]) {
                    let c = this.getChild(propertyKey)
                    this[privateKey] = c
                }
                return this[privateKey];
            },
        });
    }
}
// 获取特效
export const transition = (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => {
    let privateKey = '_' + propertyKey;
    if (!descriptor) {
        Object.defineProperty(target, propertyKey, {
            configurable: true,
            set: function (value: any) {
                this[privateKey] = value;
            },
            get: function () {
                if (!this[privateKey]) {
                    let c = this.view.getTransition(propertyKey)
                    if (!c) return null
                    this[privateKey] = c
                }
                return this[privateKey];
            },
        });
    }
}


// 页面基类
export default class View {

    static _inst: View;

    // 页面
    private _view: fgui.GComponent;
    // 控制器
    _ctrl: fgui.Controller;

    loadCall: Function;
    private packageName: string;
    private page: string;
    private ctrlName: string;
    // 装饰器覆写
    private readonly load: Function

    static resolve(path: string) {
        if (path.indexOf('/') < 0) throw Error('invalided path:' + path);
        let [packageName, page] = path.split('/');
        return {
            page,
            packageName,
        };
    }

    constructor() {
        this.load()
    }

    get asCom() {
        return this._view
    }

    get view() {
        return this._view
    }

    set view(v) {
        this._view = v
    }

    get ctrl() {
        return this._ctrl
    }

    set ctrl(v) {
        this._ctrl = v
    }

    attach() { }

    onUILoaded() {
        this.view = createObject(this.packageName, this.page).asCom;
        this.view.makeFullScreen();
        fgui.GRoot.inst.addChild(this.view);
        this.setupController();
        this.attach();
        this.loadCall && this.loadCall()
    }

    setupController() {
        this.ctrl = this.view.getController(this.ctrlName || 'ctrl');
    }

    getChild(name: string) {
        if (!this.view) return null
        return this.view.getChild(name);
    }

    blur() {
        blur(this.view.displayObject)
    }
    clearBlur() {
        clearBlur(this.view.displayObject)
    }

    dispose() {
        this.view.dispose();
    }
}
//模糊
export const blur = (sprite: Laya.Sprite) => {
    var blurFilter = new Laya.BlurFilter();
    blurFilter.strength = 5;
    sprite.filters = [blurFilter];
}
//去滤镜
export const clearBlur = (sprite: Laya.Sprite) => sprite.filters = null


// 带有动画弹窗
export class Dialog extends fgui.Window {
    // 页面
    _view: fgui.GComponent;
    // 控制器
    _ctrl: fgui.Controller;

    loadCall: Function;

    private packageName: string;
    private page: string;
    private ctrlName: string;

    // 装饰器覆写
    private readonly load: Function

    constructor() {
        super();
        this.load()
    }

    get view() {
        return this._view
    }

    set view(v) {
        this._view = v
    }

    get ctrl() {
        return this._ctrl
    }

    set ctrl(v) {
        this._ctrl = v
    }

    attach() { }

    onInit() {
        const { packageName, page } = this;
        this.view = createObject(packageName, page).asCom;
        this.contentPane = this._view;
        this.view.makeFullScreen();
        this.setPivot(0.5, 0.5);
    }

    protected doShowAnimation(): void {
        this.setScale(0.9, 0.9);
        fgui.GTween.to2(0.9, 0.9, 1, 1, 0.2)
            .setTarget(this, this.setScale)
            .setEase(fgui.EaseType.QuadOut)
            .onComplete(this.onShown, this);
    }

    onShown() {
        UIBus.event(UIEvent.BLUR)
    }

    onHide() {
        UIBus.event(UIEvent.CLEAR_BLUR)
    }

    setupController() {
        this.ctrl = this.view.getController(this.ctrlName || 'ctrl');
    }

    getChild(name: string) {
        return this.view.getChild(name);
    }

}

// 简易方法
export const open = (route: string) => {
    let Ctor = PageMap.get(route);
    if (!Ctor) throw Error('page not registered!' + route);
    return Ctor.inst
};

export const closePage = (view: View) => view.dispose();

// ui事件
export const UIBus = new Laya.EventDispatcher()

export enum UIEvent {
    BLUR = 'BLUR',
    CLEAR_BLUR = 'CLEAR_BLUR',
    TOGGLE_MAIN = 'TOGGLE_MAIN',

    JOYSTICK_MOVE = 'JOYSTICK_MOVE',
    JOYSTICK_UP = 'JOYSTICK_UP'
}